#include "QmlListener.h"

#include <QFileSystemWatcher>
#include <QQmlApplicationEngine>
#include <QQmlEngine>
#include <QQuickView>
#include <QQmlContext>
#include <QQmlComponent>
#include <QMessageBox>



QmlListenerPrivate::QmlListenerPrivate(QmlListener *parent)
    : q_ptr(parent)
{
    watcher = new QFileSystemWatcher();
}

void QmlListenerPrivate::watching()
{
    Q_Q(QmlListener);
    if(!engine && !view)
        return ;

    const QString basePath = engine ? engine->baseUrl().toString() : view->engine()->baseUrl().toString();
    QStringList paths;
    paths<<mainQml<<basePath;

    watcher->addPaths(paths);
    //    watcher->addPath(basePath);
    //    watcher->addPath(mainQml);
    QObject::connect(watcher, &QFileSystemWatcher::fileChanged, q, &QmlListener::reload);
    QObject::connect(watcher, &QFileSystemWatcher::directoryChanged, q, &QmlListener::reload);

}


QmlListener::QmlListener(const QString &mainQml, QObject *parent)
    : QObject(parent)
    , d_ptr(new QmlListenerPrivate(this))
{
    Q_D(QmlListener);
    d->mainQml = mainQml;
}

QmlListener::~QmlListener()
{

}

void QmlListener::setIndexQml(const QString &qmlFile)
{
    Q_D(QmlListener);
    if(qmlFile == d->mainQml)
        return;

    d->mainQml = qmlFile;
}

void QmlListener::listen(QQuickView *view)
{
    Q_D(QmlListener);
    d->view = view;
    d->watching();

    reload("");
}

void QmlListener::listen(QQmlApplicationEngine *engine)
{
    Q_D(QmlListener);
    d->engine = engine;
    d->watching();

    reload("");
}

void QmlListener::addPaths(const QStringList &paths)
{
    Q_D(QmlListener);
    d->watcher->addPaths(paths);
}

void QmlListener::addPath(const QString &path)
{
    Q_D(QmlListener);
    d->watcher->addPath(path);
}


void QmlListener::reload(const QString &file)
{
    Q_D(QmlListener);

    qInfo()<<"reload enter file:"<<file;

    if(d->view)
    {
        d->view->source().clear();
        d->view->setSource(QUrl());
        d->view->engine()->clearComponentCache();

        try {
            d->view->setSource(QUrl(d->mainQml));
        } catch (...) {
           // QMessageBox::warning(nullptr, "错误警告", "Qml 加载出错，请检查!");
        }
    }
    else if(d->engine)
    {
        foreach(QObject *obj, d->engine->rootObjects())
        {
            if(d->qmlObjects.contains(obj))
                continue;

            d->qmlObjects.append(obj);
            d->engine->setObjectOwnership(obj, QQmlApplicationEngine::CppOwnership);
            obj->deleteLater();
        }
        d->engine->clearComponentCache();


        try {
            d->engine->load(d->mainQml);
        } catch (...) {
         //   QMessageBox::warning(nullptr, "错误警告", "Qml 加载出错，请检查!");
        }
    }

    if(!file.isEmpty()){
        d->watcher->addPath(file);
    }
}


